<?php

namespace app\component;

use yii\base\Component;


/**
 * redis 类库
 *
 * Class RedisCache
 * @package app\component
 */
class RedisCache extends Component
{
    /**
     * @var \Redis
     */
    private $_cache;

    /**
     * @var array 配置server
     */
    private $_servers = [];

    /**
     * 初始化类
     */
    public function init()
    {
        $this->getRedis();
        $this->connect();
    }

    /**
     * 连接redis
     * @return bool
     */
    protected function connect(): bool
    {
        $servers = $this->getServers();
        $current = isset($servers[0]) && $servers[0] ? $servers[0] : [];
        if (empty($current) || !isset($current['host']) || !isset($current['port'])) {
            \Yii::error('Redis 参数错误', 'redis');
            return false;
        }
        $r = false;
        $i = 0;
        do {
            try {
                //设置连接超时时间
                $r = $this->_cache->connect($current['host'], $current['port'], $current['timeout']);
                if (isset($current['auth']) && $current['auth']) {
                    $r = $this->_cache->auth($current['auth']);
                    if (!$r) {
                        \Yii::error('Redis 授权失败', 'redis');
                    }
                }
                //设置配置项
                if (isset($current['options']) && is_array($current['options'])) {
                    foreach ($current['options'] as $opt => $value) {
                        $this->_cache->setOption($opt, $value);
                    }
                }
                //选择DB
                if (isset($current['database'])) {
                    $this->_cache->select(intval($current['database']));
                }
            } catch (\Exception $e) {
                \Yii::error($e->getMessage(), 'redis');
            }
            if ($r) {
                break;
            }
            $i++;
        } while ($i < 3);

        if (!$r) {
            \Yii::error('Redis 尝试连接' . $i . '次失败', 'redis');
        }

        return $r;
    }

    /**
     * 实例化redis
     *
     * @return false|\Redis
     */
    public function getRedis()
    {
        if ($this->_cache === null) {
            if (!extension_loaded('redis')) {
                \Yii::error('Redis 扩展不存在', 'redis');
                return false;
            }
            $this->_cache = new \Redis();
        }

        return $this->_cache;
    }

    /**
     * 获取配置
     *
     * @return array
     */
    public function getServers(): array
    {
        return $this->_servers;
    }

    /**
     * 组件初始化设置参数
     *
     * @param $config
     */
    public function setServers($config)
    {
        $this->_servers = $config;
    }

    /**
     * 切换库
     * @param int $dbName redis的库的名字
     * @return bool
     */
    public function selectDb(int $dbName): bool
    {
        return $this->_cache->select($dbName);
    }

    /**
     *
     * @param string $method
     * @param array $arguments
     * @return false|mixed
     * @throws \Exception
     */
    public function __call($method, $arguments)
    {
        if (!method_exists($this->_cache, $method)) {
            \Yii::error('redis ' . $method . ' not exists ' . json_encode($arguments), 'redis');
            throw new \Exception('redis ' . $method . ' not exists', 1100001);
        }
        return call_user_func_array(array($this->_cache, $method), $arguments);
    }

}